JavaScriptã®åçã¢ãžã¥ãŒã«æ€èšŒããã¹ã¿ãŒããŸããããå ç¢ã§å埩åã®ããã¢ããªã±ãŒã·ã§ã³ã®ããã«ã¢ãžã¥ãŒã«åŒåãã§ãã«ãŒãæ§ç¯ããæ¹æ³ãåŠã³ãŸãããã©ã°ã€ã³ããã€ã¯ãããã³ããšã³ãã«æé©ã§ãã
JavaScriptã¢ãžã¥ãŒã«åŒåãã§ãã«ãŒïŒåçã¢ãžã¥ãŒã«æ€èšŒãžã®è©³çްã¬ã€ã
é²åãç¶ããçŸä»£ã®ãœãããŠã§ã¢éçºã®äžçã«ãããŠãJavaScriptã¯åºç€ãšãªãæè¡ã§ãããã®ã¢ãžã¥ãŒã«ã·ã¹ãã ãç¹ã«ESã¢ãžã¥ãŒã«ïŒESMïŒã¯ãäŸåé¢ä¿ç®¡çã®æ··æ²ã«ç§©åºããããããŸãããTypeScriptãESLintã®ãããªããŒã«ã¯ãéçè§£æã®åŒ·åãªå±€ãæäŸããã³ãŒãããŠãŒã¶ãŒã«å±ãåã«ãšã©ãŒãæ€åºããŸããããããã¢ããªã±ãŒã·ã§ã³ã®æ§é ãã®ãã®ãåçã§ããå Žåã¯ã©ãã§ããããïŒã©ã³ã¿ã€ã ã«ãæªç¥ã®ãœãŒã¹ããããããã¯ãŠãŒã¶ãŒã®ã€ã³ã¿ã©ã¯ã·ã§ã³ã«åºã¥ããŠèªã¿èŸŒãŸããã¢ãžã¥ãŒã«ã«ã€ããŠã¯ã©ãã§ãããïŒãããéçè§£æã®éçã§ãããæ°ããªé²åŸ¡å±€ãå¿ èŠãšãããå Žæã§ãããããåçã¢ãžã¥ãŒã«æ€èšŒã§ãã
ãã®èšäºã§ã¯ãç§ãã¡ããã¢ãžã¥ãŒã«åŒåãã§ãã«ãŒããšåŒã¶åŒ·åãªãã¿ãŒã³ã玹ä»ããŸããããã¯ãåçã«ã€ã³ããŒããããJavaScriptã¢ãžã¥ãŒã«ã®åœ¢ç¶ãåãããã³å¥çŽãã©ã³ã¿ã€ã ã§æ€èšŒããããã®æŠç¥ã§ããæè»ãªãã©ã°ã€ã³ã¢ãŒããã¯ãã£ãæ§ç¯ããŠããå Žåã§ãããã€ã¯ãããã³ããšã³ãã®ã·ã¹ãã ãæ§æããŠããå Žåã§ãããããã¯åã«ã³ã³ããŒãã³ãããªã³ããã³ãã§èªã¿èŸŒãã§ããå Žåã§ãããã®ãã¿ãŒã³ã¯éçåä»ãã®å®å šæ§ãšäºæž¬å¯èœæ§ããåçã§äºæž¬äžå¯èœãªã©ã³ã¿ã€ã å®è¡ã®äžçã«ããããããšãã§ããŸãã
ãã®èšäºã§ã¯ä»¥äžã®å å®¹ãæ¢æ±ããŸãïŒ
- åçã¢ãžã¥ãŒã«ç°å¢ã«ãããéçè§£æã®éçã
- ã¢ãžã¥ãŒã«åŒåãã§ãã«ãŒãã¿ãŒã³ã®èåŸã«ããäžå¿çãªååã
- ç¬èªã®ãã§ãã«ãŒããŒãããæ§ç¯ããããã®å®è·µçãªã¹ããããã€ã¹ãããã¬ã€ãã
- ã°ããŒãã«ãªéçºããŒã ã«é©çšå¯èœãªé«åºŠãªæ€èšŒã·ããªãªãšå®äžçã®ãŠãŒã¹ã±ãŒã¹ã
- ããã©ãŒãã³ã¹ã«é¢ããèæ ®äºé ãšå®è£ ã®ãã¹ããã©ã¯ãã£ã¹ã
é²åããJavaScriptã¢ãžã¥ãŒã«ç°å¢ãšåçãªãžã¬ã³ã
ã©ã³ã¿ã€ã æ€èšŒã®å¿ èŠæ§ãçè§£ããããã«ã¯ããŸãç§ãã¡ãã©ã®ããã«ããŠããã«è³ã£ãã®ããçè§£ããå¿ èŠããããŸããJavaScriptã¢ãžã¥ãŒã«ã®éã®ãã¯ãæŽç·ŽåºŠãå¢ããŠãããã®ã§ããã
ã°ããŒãã«æ±æããæ§é åãããã€ã³ããŒããž
åæã®JavaScriptéçºã¯ããã°ãã°<script>ã¿ã°ã®ç®¡çãšããäžå®å®ãªäœæ¥ã§ãããããã¯ã°ããŒãã«ã¹ã³ãŒããæ±æãã倿°ãè¡çªããå¯èœæ§ããããäŸåé¢ä¿ã®é åºã¯èåŒ±ã§æåã®ããã»ã¹ã§ãããããã解決ããããã«ãã³ãã¥ããã£ã¯CommonJSïŒNode.jsã«ãã£ãŠæ®åïŒãéåæã¢ãžã¥ãŒã«å®çŸ©ïŒAMDïŒã®ãããªæšæºãäœæããŸããããããã¯åœ¹ç«ã¡ãŸããããèšèªèªäœã«ã¯ãã€ãã£ããªè§£æ±ºçããããŸããã§ããã
ããã§ç»å Žããã®ãESã¢ãžã¥ãŒã«ïŒESMïŒã§ããECMAScript 2015ïŒES6ïŒã®äžéšãšããŠæšæºåãããESMã¯ãimportããã³exportæã«ãã£ãŠãçµ±äžãããéçãªã¢ãžã¥ãŒã«æ§é ãèšèªã«ãããããŸãããããã§ã®ããŒã¯ãŒãã¯éçã§ããã¢ãžã¥ãŒã«ã°ã©ãïŒã©ã®ã¢ãžã¥ãŒã«ãã©ã®ã¢ãžã¥ãŒã«ã«äŸåããŠãããïŒã¯ãã³ãŒããå®è¡ããããšãªã決å®ã§ããŸããããããWebpackãRollupã®ãããªãã³ãã©ãŒãããªãŒã·ã§ã€ãã³ã°ãå®è¡ã§ããçç±ã§ãããTypeScriptããã¡ã€ã«éã§åå®çŸ©ã远跡ã§ããçç±ã§ãã
åçimport()ã®å°é
éçãªã°ã©ãã¯æé©åã«ã¯æé©ã§ãããçŸä»£ã®Webã¢ããªã±ãŒã·ã§ã³ã¯ããè¯ããŠãŒã¶ãŒäœéšã®ããã«åçæ§ãèŠæ±ããŸãããã°ã€ã³ããŒãžã衚瀺ããããã ãã«ãæ°ã¡ã¬ãã€ãã®ã¢ããªã±ãŒã·ã§ã³ãã³ãã«å
šäœãèªã¿èŸŒã¿ããã¯ãããŸããããããåçãªimport()åŒã®å°å
¥ã«ã€ãªãããŸããã
éçãªå¯Ÿå¿ç©ãšã¯ç°ãªããimport()ã¯Promiseãè¿ã颿°ã®ãããªæ§é ã§ããããã«ãããã¢ãžã¥ãŒã«ããªã³ããã³ãã§èªã¿èŸŒãããšãã§ããŸãïŒ
// ãŠãŒã¶ãŒããã¿ã³ãã¯ãªãã¯ãããšãã«ã®ã¿ãéãã°ã©ãã©ã€ãã©ãªãèªã¿èŸŒã
const showReportButton = document.getElementById('show-report');
showReportButton.addEventListener('click', async () => {
try {
const ChartingLibrary = await import('./heavy-charting-library.js');
ChartingLibrary.renderChart();
} catch (error) {
console.error("ã°ã©ãã¢ãžã¥ãŒã«ã®èªã¿èŸŒã¿ã«å€±æããŸãã:", error);
}
});
ãã®æ©èœã¯ãã³ãŒãåå²ãé
å»¶èªã¿èŸŒã¿ãšãã£ãçŸä»£ã®ããã©ãŒãã³ã¹ãã¿ãŒã³ã®æ ¹å¹¹ããªããã®ã§ããããããããã¯æ ¹æ¬çãªäžç¢ºå®æ§ãå°å
¥ããŸãããã®ã³ãŒããæžããŠããæç¹ã§ãç§ãã¡ã¯ããä»®å®ãããŠããŸããããã¯ã'./heavy-charting-library.js'ãæçµçã«èªã¿èŸŒãŸãããšããç¹å®ã®åœ¢ç¶ããã®å Žåã¯renderChartãšããååä»ããšã¯ã¹ããŒãã§ãããã颿°ã§ãããšãã圢ç¶ãæã€ã ããããšããä»®å®ã§ããéçè§£æããŒã«ã¯ãã¢ãžã¥ãŒã«ãæã
ã®ãããžã§ã¯ãå
ã«ããå Žåããããæšæž¬ã§ããããšãå€ãã§ãããã¢ãžã¥ãŒã«ãã¹ãåçã«æ§ç¯ãããããã¢ãžã¥ãŒã«ãå€éšã®ä¿¡é Œã§ããªããœãŒã¹ããæ¥ãå Žåã«ã¯ç¡åã§ãã
éçæ€èšŒ vs. åçæ€èšŒïŒã®ã£ãããåãã
ç§ãã¡ã®ãã¿ãŒã³ãçè§£ããããã«ã¯ã2ã€ã®æ€èšŒå²åŠãåºå¥ããããšãéèŠã§ãã
éçè§£æïŒã³ã³ãã€ã«æã®å®è·è
TypeScriptãFlowãESLintã®ãããªããŒã«ã¯éçè§£æãå®è¡ããŸãããããã¯ã³ãŒããå®è¡ããã«èªã¿èŸŒã¿ã宣èšãããå®çŸ©ïŒ.d.tsãã¡ã€ã«ãJSDocã³ã¡ã³ãããŸãã¯ã€ã³ã©ã€ã³åïŒã«åºã¥ããŠãã®æ§é ãšåãåæããŸãã
- é·æïŒéçºãµã€ã¯ã«ã®æ©ã段éã§ãšã©ãŒããã£ããããåªãããªãŒãã³ã³ããªãŒããšIDEçµ±åãæäŸããã©ã³ã¿ã€ã ã®ããã©ãŒãã³ã¹ã³ã¹ãããããŸããã
- çæïŒã©ã³ã¿ã€ã ã§ããããããªãããŒã¿ãã³ãŒãæ§é ãæ€èšŒããããšã¯ã§ããŸãããã©ã³ã¿ã€ã ã®çŸå®ãéçãªä»®å®ãšäžèŽãããšä¿¡é ŒããŠããŸããããã«ã¯APIã¬ã¹ãã³ã¹ããŠãŒã¶ãŒå ¥åããããŠæã ã«ãšã£ãŠéèŠãªãåçã«èªã¿èŸŒãŸããã¢ãžã¥ãŒã«ã®å 容ãå«ãŸããŸãã
åçæ€èšŒïŒã©ã³ã¿ã€ã ã®éçª
åçæ€èšŒã¯ã³ãŒããå®è¡ãããŠããéã«è¡ãããŸããããã¯é²åŸ¡çããã°ã©ãã³ã°ã®äžåœ¢æ ã§ãããããŒã¿ãäŸåé¢ä¿ã䜿çšããåã«ãããããæåŸ ããæ§é ãæã£ãŠããããšãæç€ºçã«ãã§ãã¯ããŸãã
- é·æïŒãœãŒã¹ã«é¢ä¿ãªããããããããŒã¿ãæ€èšŒã§ããŸããäºæããªãã©ã³ã¿ã€ã ã®å€æŽã«å¯Ÿããå ç¢ãªã»ãŒããã£ããããæäŸãããšã©ãŒãã·ã¹ãã å šäœã«äŒæããã®ãé²ããŸãã
- çæïŒã©ã³ã¿ã€ã ã®ããã©ãŒãã³ã¹ã³ã¹ãããããã³ãŒããåé·ã«ãªãå¯èœæ§ããããŸãããšã©ãŒã¯ã©ã€ããµã€ã¯ã«ã®åŸåãã€ãŸãã³ã³ãã€ã«æã§ã¯ãªãå®è¡äžã«ãã£ãããããŸãã
ã¢ãžã¥ãŒã«åŒåãã§ãã«ãŒã¯ãESã¢ãžã¥ãŒã«ã«ç¹åããåçæ€èšŒã®äžåœ¢æ ã§ããããã¯ãæã ã®ã¢ããªã±ãŒã·ã§ã³ã®éçãªäžçãšãã©ã³ã¿ã€ã ã¢ãžã¥ãŒã«ã®äžç¢ºå®ãªäžçãåºäŒãåçãªå¢çã§å¥çŽã匷å¶ãããæ©æž¡ã圹ãšããŠæ©èœããŸãã
ã¢ãžã¥ãŒã«åŒåãã§ãã«ãŒãã¿ãŒã³ã®ç޹ä»
ãã®æ žå¿ã«ãããŠããã®ãã¿ãŒã³ã¯é©ãã»ã©ã·ã³ãã«ã§ããããã¯äž»ã«3ã€ã®ã³ã³ããŒãã³ãã§æ§æãããŠããŸãïŒ
- ã¢ãžã¥ãŒã«ã¹ããŒãïŒã¢ãžã¥ãŒã«ã«æåŸ ãããã圢ç¶ããŸãã¯ãå¥çŽããå®çŸ©ãã宣èšçãªãªããžã§ã¯ãããã®ã¹ããŒãã¯ãã©ã®ååä»ããšã¯ã¹ããŒããååšãã¹ããããããã®åã¯äœãããããŠããã©ã«ããšã¯ã¹ããŒãã®æåŸ ãããåãæå®ããŸãã
- ããªããŒã¿ãŒé¢æ°ïŒå®éã®ã¢ãžã¥ãŒã«ãªããžã§ã¯ãïŒ
import()Promiseãã解決ããããã®ïŒãšã¹ããŒããåãåããäž¡è ãæ¯èŒãã颿°ãã¢ãžã¥ãŒã«ãã¹ããŒãã§å®çŸ©ãããå¥çŽãæºãããŠããã°ã颿°ã¯æåè£ã«è¿ããŸããããã§ãªããã°ã説æçãªãšã©ãŒãã¹ããŒããŸãã - çµ±åãã€ã³ãïŒåçãª
import()åŒã³åºãã®çŽåŸãéåžžã¯async颿°å ã§ãèªã¿èŸŒã¿ãšæ€èšŒã®äž¡æ¹ã®å€±æãåªé ã«åŠçããããã«try...catchãããã¯ã§å²ãã§ããªããŒã¿ãŒé¢æ°ã䜿çšããŸãã
çè«ããå®è·µã«ç§»ããç¬èªã®ãã§ãã«ãŒãæ§ç¯ããŸãããã
ã¢ãžã¥ãŒã«åŒãã§ãã«ãŒããŒãããæ§ç¯ãã
ã·ã³ãã«ã§ãããªãã广çãªã¢ãžã¥ãŒã«ããªããŒã¿ãŒãäœæããŸããæ§ã ãªãŠã£ãžã§ãããã©ã°ã€ã³ãåçã«èªã¿èŸŒãããšãã§ããããã·ã¥ããŒãã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããŠãããšæ³åããŠãã ããã
ã¹ããã1ïŒãã©ã°ã€ã³ã¢ãžã¥ãŒã«ã®äŸ
ãŸããæå¹ãªãã©ã°ã€ã³ã¢ãžã¥ãŒã«ãå®çŸ©ããŸãããããã®ã¢ãžã¥ãŒã«ã¯ãèšå®ãªããžã§ã¯ããã¬ã³ããªã³ã°é¢æ°ããããŠãŠã£ãžã§ããèªäœã®ããã®ããã©ã«ãã¯ã©ã¹ããšã¯ã¹ããŒãããªããã°ãªããŸããã
ãã¡ã€ã«: /plugins/weather-widget.js
Loading...export const version = '1.0.0';
export const config = {
requiresApiKey: true,
updateInterval: 300000 // 5 minutes
};
export function render(element) {
element.innerHTML = 'Weather Widget
ã¹ããã2ïŒã¹ããŒãã®å®çŸ©
次ã«ããã©ã°ã€ã³ã¢ãžã¥ãŒã«ãæºæ ããªããã°ãªããªãå¥çŽãèšè¿°ããã¹ããŒããªããžã§ã¯ããäœæããŸããç§ãã¡ã®ã¹ããŒãã¯ãååä»ããšã¯ã¹ããŒããšããã©ã«ããšã¯ã¹ããŒãã«å¯ŸããæåŸ ãå®çŸ©ããŸãã
const WIDGET_MODULE_SCHEMA = {
exports: {
// ãããã®ååä»ããšã¯ã¹ããŒããšç¹å®ã®åãæåŸ
ãã
named: {
version: 'string',
config: 'object',
render: 'function'
},
// 颿°ïŒã¯ã©ã¹çšïŒã§ããããã©ã«ããšã¯ã¹ããŒããæåŸ
ãã
default: 'function'
}
};
ãã®ã¹ããŒãã¯å®£èšçã§èªã¿ãããã§ããããã¯ããŠã£ãžã§ãããã§ããããšãæå³ããä»»æã®ã¢ãžã¥ãŒã«ã«å¯ŸããAPIå¥çŽãæç¢ºã«äŒããŸãã
ã¹ããã3ïŒããªããŒã¿ãŒé¢æ°ã®äœæ
ããŠãäžå¿çãªããžãã¯ã§ããç§ãã¡ã®`validateModule`颿°ã¯ã¹ããŒããå埩åŠçããã¢ãžã¥ãŒã«ãªããžã§ã¯ãããã§ãã¯ããŸãã
/**
* åçã«ã€ã³ããŒããããã¢ãžã¥ãŒã«ãã¹ããŒãã«å¯ŸããŠæ€èšŒããŸãã
* @param {object} module - import()åŒã³åºãããã®ã¢ãžã¥ãŒã«ãªããžã§ã¯ãã
* @param {object} schema - æåŸ
ãããã¢ãžã¥ãŒã«æ§é ãå®çŸ©ããã¹ããŒãã
* @param {string} moduleName - ããè¯ããšã©ãŒã¡ãã»ãŒãžã®ããã®ã¢ãžã¥ãŒã«ã®èå¥åã
* @throws {Error} æ€èšŒã倱æããå Žåã
*/
function validateModule(module, schema, moduleName = 'Unknown Module') {
// ããã©ã«ããšã¯ã¹ããŒãã®ãã§ãã¯
if (schema.exports.default) {
if (!('default' in module)) {
throw new Error(`[${moduleName}] æ€èšŒãšã©ãŒ: ããã©ã«ããšã¯ã¹ããŒãããããŸããã`);
}
const defaultExportType = typeof module.default;
if (defaultExportType !== schema.exports.default) {
throw new Error(
`[${moduleName}] æ€èšŒãšã©ãŒ: ããã©ã«ããšã¯ã¹ããŒãã®åãééã£ãŠããŸããæåŸ
å€ '${schema.exports.default}', å®éå€ '${defaultExportType}'ã`
);
}
}
// ååä»ããšã¯ã¹ããŒãã®ãã§ãã¯
if (schema.exports.named) {
for (const exportName in schema.exports.named) {
if (!(exportName in module)) {
throw new Error(`[${moduleName}] æ€èšŒãšã©ãŒ: ååä»ããšã¯ã¹ããŒã '${exportName}' ããããŸããã`);
}
const expectedType = schema.exports.named[exportName];
const actualType = typeof module[exportName];
if (actualType !== expectedType) {
throw new Error(
`[${moduleName}] æ€èšŒãšã©ãŒ: ååä»ããšã¯ã¹ããŒã '${exportName}' ã®åãééã£ãŠããŸããæåŸ
å€ '${expectedType}', å®éå€ '${actualType}'ã`
);
}
}
}
console.log(`[${moduleName}] ã¢ãžã¥ãŒã«ã¯æ£åžžã«æ€èšŒãããŸããã`);
}
ãã®é¢æ°ã¯ããµãŒãããŒãã£è£œãŸãã¯åçã«çæãããã¢ãžã¥ãŒã«ã®åé¡ããããã°ããäžã§éåžžã«éèŠãªãå ·äœçã§å®è¡å¯èœãªãšã©ãŒã¡ãã»ãŒãžãæäŸããŸãã
ã¹ããã4ïŒãã¹ãŠããŸãšãã
æåŸã«ããã©ã°ã€ã³ãèªã¿èŸŒãã§æ€èšŒãã颿°ãäœæããŸãããããã®é¢æ°ã¯ãç§ãã¡ã®åçèªã¿èŸŒã¿ã·ã¹ãã ã®äž»èŠãªãšã³ããªãŒãã€ã³ãã«ãªããŸãã
async function loadWidgetPlugin(path) {
try {
console.log(`ãŠã£ãžã§ããã®èªã¿èŸŒã¿ã詊ã¿ãŸã: ${path}`);
const widgetModule = await import(path);
// éèŠãªæ€èšŒã¹ãããïŒ
validateModule(widgetModule, WIDGET_MODULE_SCHEMA, path);
// æ€èšŒãéãã°ãã¢ãžã¥ãŒã«ã®ãšã¯ã¹ããŒããå®å
šã«äœ¿çšã§ãã
const container = document.getElementById('widget-container');
widgetModule.render(container);
const widgetInstance = new widgetModule.default('YOUR_API_KEY');
const data = await widgetInstance.fetchData();
console.log('ãŠã£ãžã§ããããŒã¿:', data);
return widgetModule;
} catch (error) {
console.error(`'${path}' ããã®ãŠã£ãžã§ããã®èªã¿èŸŒã¿ãŸãã¯æ€èšŒã«å€±æããŸããã`);
console.error(error);
// ãŠãŒã¶ãŒã«ãã©ãŒã«ããã¯UIã衚瀺ããå¯èœæ§ããã
return null;
}
}
// 䜿çšäŸ:
loadWidgetPlugin('/plugins/weather-widget.js');
ã§ã¯ãéæºæ ã®ã¢ãžã¥ãŒã«ãèªã¿èŸŒãããšãããšã©ããªããèŠãŠã¿ãŸãããïŒ
ãã¡ã€ã«: /plugins/faulty-widget.js
// 'version' ãšã¯ã¹ããŒãããªã
// 'render' ã¯é¢æ°ã§ã¯ãªããªããžã§ã¯ã
export const config = { requiresApiKey: false };
export const render = { message: 'I should be a function!' };
export default () => {
console.log("I'm a default function, not a class.");
};
loadWidgetPlugin('/plugins/faulty-widget.js')ãåŒã³åºããšãç§ãã¡ã®`validateModule`颿°ããšã©ãŒããã£ããããŠã¹ããŒããwidgetModule.render is not a functionã®ãããªã©ã³ã¿ã€ã ãšã©ãŒã«ããã¢ããªã±ãŒã·ã§ã³ã®ã¯ã©ãã·ã¥ãé²ããŸãã代ããã«ãã³ã³ãœãŒã«ã«æç¢ºãªãã°ã衚瀺ãããŸãïŒ
' /plugins/faulty-widget.js' ããã®ãŠã£ãžã§ããã®èªã¿èŸŒã¿ãŸãã¯æ€èšŒã«å€±æããŸããã
Error: [/plugins/faulty-widget.js] æ€èšŒãšã©ãŒ: ååä»ããšã¯ã¹ããŒã 'version' ããããŸããã
ç§ãã¡ã®catchãããã¯ã¯ãããåªé
ã«åŠçããã¢ããªã±ãŒã·ã§ã³ã¯å®å®ãããŸãŸã§ãã
é«åºŠãªæ€èšŒã·ããªãª
åºæ¬çãª`typeof`ãã§ãã¯ã¯åŒ·åã§ãããããè€éãªå¥çŽãæ±ãããã«ãã¿ãŒã³ãæ¡åŒµããããšãã§ããŸãã
æ·±ããªããžã§ã¯ããšé åã®æ€èšŒ
ãšã¯ã¹ããŒãããã`config`ãªããžã§ã¯ããç¹å®ã®åœ¢ç¶ãæã€ããšãä¿èšŒããå¿ èŠãããå Žåã¯ã©ãã§ããããïŒ'object'ã«å¯ŸããåçŽãª`typeof`ãã§ãã¯ã§ã¯äžååã§ããããã¯ãå°çšã®ã¹ããŒãæ€èšŒã©ã€ãã©ãªãçµ±åããã®ã«æé©ãªå Žæã§ããZodãYupããŸãã¯Joiã®ãããªã©ã€ãã©ãªãããã«åªããŠããŸãã
Zodã䜿çšããŠãã衚çŸåè±ããªã¹ããŒããäœæããæ¹æ³ãèŠãŠã¿ãŸãããïŒ
// 1. ãŸããZodãã€ã³ããŒãããå¿
èŠããããŸã
// import { z } from 'zod';
// 2. Zodã䜿çšããŠãã匷åãªã¹ããŒããå®çŸ©ãã
const ZOD_WIDGET_SCHEMA = z.object({
version: z.string(),
config: z.object({
requiresApiKey: z.boolean(),
updateInterval: z.number().positive().optional()
}),
render: z.function().args(z.instanceof(HTMLElement)).returns(z.void()),
default: z.function() // Zodã¯ã¯ã©ã¹ã³ã³ã¹ãã©ã¯ã¿ãç°¡åã«æ€èšŒã§ããŸãããã'function'ã¯è¯ãåºçºç¹ã§ãã
});
// 3. æ€èšŒããžãã¯ãæŽæ°ãã
async function loadAndValidateWithZod(path) {
try {
const widgetModule = await import(path);
// Zodã®parseã¡ãœããã¯æ€èšŒãã倱ææã«ã¹ããŒããŸã
ZOD_WIDGET_SCHEMA.parse(widgetModule);
console.log(`[${path}] ã¢ãžã¥ãŒã«ã¯Zodã§æ£åžžã«æ€èšŒãããŸããã`);
return widgetModule;
} catch (error) {
console.error(`${path} ã®æ€èšŒã«å€±æããŸãã:`, error.errors);
return null;
}
}
Zodã®ãããªã©ã€ãã©ãªã䜿çšãããšãã¹ããŒããããå ç¢ã§èªã¿ããããªãããã¹ãããããªããžã§ã¯ããé åãåæåããã®ä»ã®è€éãªåãç°¡åã«æ±ãããšãã§ããŸãã
颿°ã·ã°ããã£ã®æ€èšŒ
颿°ã®æ£ç¢ºãªã·ã°ããã£ïŒåŒæ°ã®åãšæ»ãå€ã®åïŒãæ€èšŒããããšã¯ããã¬ãŒã³ãªJavaScriptã§ã¯éåžžã«å°é£ã§ããZodã®ãããªã©ã€ãã©ãªã¯ããçšåºŠã®å©ããæäŸããŸãããçŸå®çãªã¢ãããŒãã¯ã颿°ã®`length`ããããã£ããã§ãã¯ããããšã§ããããã¯ããã®å®çŸ©ã§å®£èšãããæåŸ ãããåŒæ°ã®æ°ã瀺ããŸãã
// ããªããŒã¿ãŒå
ã§ã颿°ãšã¯ã¹ããŒãã®å Žå:
const expectedArgCount = 1;
if (module.render.length !== expectedArgCount) {
throw new Error(`æ€èšŒãšã©ãŒ: 'render' 颿°ã¯ ${expectedArgCount} åã®åŒæ°ãæåŸ
ããŠããŸãããã${module.render.length} å宣èšãããŠããŸãã`);
}
泚æïŒããã¯å®å šã§ã¯ãããŸãããã¬ã¹ããã©ã¡ãŒã¿ãããã©ã«ããã©ã¡ãŒã¿ããŸãã¯åå²ä»£å ¥ãããåŒæ°ãèæ ®ããŠããŸãããããããããã¯æçšã§ç°¡åãªå¥å šæ§ãã§ãã¯ãšããŠæ©èœããŸãã
ã°ããŒãã«ãªæèã§ã®å®äžçã®ãŠãŒã¹ã±ãŒã¹
ãã®ãã¿ãŒã³ã¯åãªãçè«çãªæŒç¿ã§ã¯ãããŸãããäžçäžã®éçºããŒã ãçŽé¢ããçŸå®äžçã®åé¡ã解決ããŸãã
1. ãã©ã°ã€ã³ã¢ãŒããã¯ãã£
ããã¯å€å žçãªãŠãŒã¹ã±ãŒã¹ã§ããIDEïŒVS CodeïŒãCMSïŒWordPressïŒããã¶ã€ã³ããŒã«ïŒFigmaïŒã®ãããªã¢ããªã±ãŒã·ã§ã³ã¯ããµãŒãããŒãã£ã®ãã©ã°ã€ã³ã«äŸåããŠããŸããã¢ãžã¥ãŒã«ããªããŒã¿ãŒã¯ãã³ã¢ã¢ããªã±ãŒã·ã§ã³ããã©ã°ã€ã³ãèªã¿èŸŒãå¢çã§äžå¯æ¬ ã§ããããã«ããããã©ã°ã€ã³ãå¿ èŠãªé¢æ°ïŒäŸïŒ`activate`ã`deactivate`ïŒããªããžã§ã¯ããæ£ããçµ±åããããã«æäŸããããšãä¿èšŒããäžã€ã®äžè¯ãã©ã°ã€ã³ãã¢ããªã±ãŒã·ã§ã³å šäœãã¯ã©ãã·ã¥ãããã®ãé²ããŸãã
2. ãã€ã¯ãããã³ããšã³ã
ãã€ã¯ãããã³ããšã³ãã¢ãŒããã¯ãã£ã§ã¯ããã°ãã°ç°ãªãå°ççãªå Žæã«ããç°ãªãããŒã ãããã倧ããªã¢ããªã±ãŒã·ã§ã³ã®åéšåãç¬ç«ããŠéçºããŸããã¡ã€ã³ã®ã¢ããªã±ãŒã·ã§ã³ã·ã§ã«ã¯ããããã®ãã€ã¯ãããã³ããšã³ããåçã«èªã¿èŸŒã¿ãŸããã¢ãžã¥ãŒã«åŒãã§ãã«ãŒã¯ãçµ±åãã€ã³ãã§ãAPIå¥çŽã®åŒ·å¶è ããšããŠæ©èœãããã€ã¯ãããã³ããšã³ããã¬ã³ããªã³ã°ã詊ã¿ãåã«ãæåŸ ãããããŠã³ã颿°ãã³ã³ããŒãã³ããå ¬éããŠããããšãä¿èšŒããŸããããã«ãããããŒã éã®çµåãç·©åããããããã€ã®å€±æãã·ã¹ãã å šäœã«æ³¢åããã®ãé²ããŸãã
3. åçãªã³ã³ããŒãã³ãã®ããŒãèšå®ãŸãã¯ããŒãžã§ãã³ã°
ãŠãŒã¶ãŒã®åœã«åºã¥ããŠç°ãªãæ¯æãåŠçã³ã³ããŒãã³ããèªã¿èŸŒãå¿ èŠãããåœéçãªeã³ããŒã¹ãµã€ããæ³åããŠã¿ãŠãã ãããåã³ã³ããŒãã³ãã¯ç¬èªã®ã¢ãžã¥ãŒã«ã«ãããããããŸããã
const userCountry = 'DE'; // ãã€ã
const paymentModulePath = `/components/payment/${userCountry}.js`;
// ããªããŒã¿ãŒã䜿çšããŠãåœåºæã®ã¢ãžã¥ãŒã«ãæåŸ
ããã
// 'PaymentProcessor' ã¯ã©ã¹ãš 'getFees' 颿°ãå
¬éããŠããããšã確èªãã
const paymentModule = await loadAndValidate(paymentModulePath, PAYMENT_SCHEMA);
if (paymentModule) {
// æ¯æããããŒãç¶è¡ãã
}
ããã«ããããã¹ãŠã®åœåºæã®å®è£ ããã³ã¢ã¢ããªã±ãŒã·ã§ã³ã®èŠæ±ããã€ã³ã¿ãŒãã§ãŒã¹ã«æºæ ããŠããããšãä¿èšŒãããŸãã
4. A/Bãã¹ããšãã£ãŒãã£ãŒãã©ã°
A/Bãã¹ããå®è¡ããéããããŠãŒã¶ãŒã°ã«ãŒãã«ã¯`component-variant-A.js`ããå¥ã®ã°ã«ãŒãã«ã¯`component-variant-B.js`ãåçã«èªã¿èŸŒããããããŸãããããªããŒã¿ãŒã¯ãäž¡æ¹ã®ããªã¢ã³ããå éšçãªéãã«ãããããããåãå ¬éAPIãå ¬éããŠããããšãä¿èšŒããã¢ããªã±ãŒã·ã§ã³ã®æ®ãã®éšåãããããšäºæçã«å¯Ÿè©±ã§ããããã«ããŸãã
ããã©ãŒãã³ã¹ã«é¢ããèæ ®äºé ãšãã¹ããã©ã¯ãã£ã¹
ã©ã³ã¿ã€ã æ€èšŒã¯ç¡æã§ã¯ãããŸãããCPUãµã€ã¯ã«ãæ¶è²»ããã¢ãžã¥ãŒã«ã®èªã¿èŸŒã¿ã«ããããªé å»¶ã远å ããå¯èœæ§ããããŸãã圱é¿ã軜æžããããã®ãã¹ããã©ã¯ãã£ã¹ãããã€ã玹ä»ããŸãïŒ
- éçºã§ã¯äœ¿çšããæ¬çªã§ã¯ãã°ãèšé²ããïŒããã©ãŒãã³ã¹ãéèŠãªã¢ããªã±ãŒã·ã§ã³ã§ã¯ãéçºç°å¢ãšã¹ããŒãžã³ã°ç°å¢ã§å®å šã§å³æ Œãªæ€èšŒïŒãšã©ãŒãã¹ããŒããïŒãå®è¡ããããšãæ€èšãããããããŸãããæ¬çªç°å¢ã§ã¯ãæ€èšŒã®å€±æãå®è¡ã忢ãããã代ããã«ãšã©ãŒãã©ããã³ã°ãµãŒãã¹ã«å ±åãããããã®ã³ã°ã¢ãŒããã«åãæ¿ããããšãã§ããŸããããã«ããããŠãŒã¶ãŒäœéšã«åœ±é¿ãäžããããšãªãå¯èŠ³æž¬æ§ãåŸãããŸãã
- å¢çã§æ€èšŒããïŒãã¹ãŠã®åçã€ã³ããŒããæ€èšŒããå¿ èŠã¯ãããŸãããã·ã¹ãã ã®éèŠãªå¢çã«çŠç¹ãåœãŠãŠãã ããïŒãµãŒãããŒãã£ã®ã³ãŒããèªã¿èŸŒãŸããå Žæããã€ã¯ãããã³ããšã³ããæ¥ç¶ããå ŽæããŸãã¯ä»ã®ããŒã ããã®ã¢ãžã¥ãŒã«ãçµ±åãããå Žæãªã©ã§ãã
- æ€èšŒçµæããã£ãã·ã¥ããïŒåãã¢ãžã¥ãŒã«ãã¹ãè€æ°åèªã¿èŸŒãå Žåãåæ€èšŒããå¿ èŠã¯ãããŸãããæ€èšŒçµæããã£ãã·ã¥ããããšãã§ããŸããåçŽãª`Map`ã䜿çšããŠãåã¢ãžã¥ãŒã«ãã¹ã®æ€èšŒã¹ããŒã¿ã¹ãä¿åã§ããŸãã
const validationCache = new Map();
async function loadAndValidateCached(path, schema) {
if (validationCache.get(path) === 'valid') {
return import(path);
}
if (validationCache.get(path) === 'invalid') {
throw new Error(`ã¢ãžã¥ãŒã« ${path} ã¯ç¡å¹ã§ããããšãç¥ãããŠããŸãã`);
}
try {
const module = await import(path);
validateModule(module, schema, path);
validationCache.set(path, 'valid');
return module;
} catch (error) {
validationCache.set(path, 'invalid');
throw error;
}
}
çµè«ïŒããå埩åã®ããã·ã¹ãã ã®æ§ç¯
éçè§£æã¯ãJavaScriptéçºã®ä¿¡é Œæ§ãæ ¹æ¬çã«åäžãããŸãããããããç§ãã¡ã®ã¢ããªã±ãŒã·ã§ã³ãããåçã§åæ£çã«ãªãã«ã€ããŠãçŽç²ã«éçãªã¢ãããŒãã®éçãèªèããªããã°ãªããŸãããåçãªimport()ã«ãã£ãŠå°å
¥ãããäžç¢ºå®æ§ã¯æ¬ é¥ã§ã¯ãªãã匷åãªã¢ãŒããã¯ãã£ãã¿ãŒã³ãå¯èœã«ããæ©èœã§ãã
ã¢ãžã¥ãŒã«åŒåãã§ãã«ãŒãã¿ãŒã³ã¯ããã®ãã€ãããºã ãèªä¿¡ãæã£ãŠåãå ¥ããããã«å¿ èŠãªã©ã³ã¿ã€ã ã®ã»ãŒããã£ããããæäŸããŸããã¢ããªã±ãŒã·ã§ã³ã®åçãªå¢çã§å¥çŽãæç€ºçã«å®çŸ©ãã匷å¶ããããšã«ãããããå埩åãããããããã°ã容æã§ãäºæãã¬å€æŽã«å¯ŸããŠããå ç¢ãªã·ã¹ãã ãæ§ç¯ããããšãã§ããŸãã
é å»¶èªã¿èŸŒã¿ã³ã³ããŒãã³ããæã€å°èŠæš¡ãªãããžã§ã¯ãã§äœæ¥ããŠããå Žåã§ãããã€ã¯ãããã³ããšã³ãã®å·šå€§ã§ã°ããŒãã«ã«åæ£ããã·ã¹ãã ã§äœæ¥ããŠããå Žåã§ããåçã¢ãžã¥ãŒã«æ€èšŒãžã®å°ããªæè³ãå®å®æ§ãšä¿å®æ§ã«ãããŠå€§ããªå©çãããããå Žæãæ€èšããŠãã ãããããã¯ãçæ³çãªæ¡ä»¶äžã§æ©èœããã ãã§ãªããã©ã³ã¿ã€ã ã®çŸå®ã«çŽé¢ããŠã匷åºã§ããç¶ãããœãããŠã§ã¢ãäœæããããã®ç©æ¥µçãªäžæ©ã§ãã